<?php
namespace Lavender\Dao;
use Lavender\Core;
use Lavender\Errno;

/**
 * table access class
 *
 */
abstract class MongoTable
{
	/**
	 * database system
	 * @var string
	 */
	protected $driver = 'mongodb';

	/**
	 * database config name
	 * @var string
	 */
	protected $database = 'demo_database';

	/**
	 * table
	 * @var string
	 */
	protected $table = 'demo_table';

	protected $db_handle;

	/**
	 * all instances cache
	 * @var array
	 */
	private static $instances = array();

	public function __construct()
	{
		$this->db_handle = Core::get_database($this->driver, $this->database);
	}

	/**
	 * get instance singletion
	 *
	 * @return Table
	 */
	public static function instance()
	{
		$class = get_called_class();
		if (empty(self::$instances[$class]) ) {
			self::$instances[$class] = new $class();
		}
		return self::$instances[$class];
	}

	/**
	 * multipie get
	 *
	 * @param array $query  要查询的字段
	 * @param array $fields 返回的字段
	 * @param array $order  按哪些字段进行排序 (eg. array('id' => 1, 'name' => -1))
	 * @param int $offset
	 * @param int $length
	 *
	 * @return array
	 */
	public function get($query = array(), $fields = array(), $order = '', $offset = '', $length = '', $is_res_id = false, $reconnect = false)
	{
		return $this->db_handle->get($this->table, $query, $fields, $order, $offset, $length, $is_res_id, $reconnect);
	}

	/**
	 * single record get
	 *
	 * @param int $id
	 * @param array $filter filter condition
	 * @param string $order
	 *
	 * @return mixed
	 */
	public function get_single($query = array(), $fields = array())
	{
		return $this->db_handle->get_single($this->table, $query, $fields);
	}


	/**
	 * count
	 * @param array  $query  要搜索的字段
	 * @param int    $offset limit offset
	 * @param int    $length limit size
	 *
	 * @return int
	 */
	public function count($query = array(), $offset = null, $length = null)
	{
		return $this->db_handle->count($this->table, $query, $offset, $length);
	}

	/**
	 * insert records
	 * @param  array $content 插入的内容
	 * @param  array  $options Options for the insert
	 */
	public function insert($content, $options = array())
	{
		if(!is_array($content)){
			throw new Exception("param must be array", Errno::PARAM_INVALID);
		}
		return $this->db_handle->insert($this->table, $content, $options);
	}

	/**
	 * batchinsert records
	 * @param  array $content 插入的内容
	 * @param  array  $options Options for the insert
	 */
	public function batch_insert($content, $options = array())
	{
		if(!is_array($content)){
			throw new Exception("param must be array", Errno::PARAM_INVALID);
		}
		return $this->db_handle->batch_insert($this->table, $content, $options);
	}

	/**
	 * update the objects 
	 * @param  array $criteria   更新的条件
	 * @param  array $new_object 更新的内容
	 * @param  array  $options    更新的额外设置
	 */
	public function update($criteria, $new_object, $is_reconnect = false, $options = array())
	{
		if(!is_array($criteria)){
			throw new Exception("param must be array", Errno::PARAM_INVALID);
		}
		if(!is_array($new_object)){
			throw new Exception("param must be array", Errno::PARAM_INVALID);
		}
		return $this->db_handle->update($this->table, $criteria, $new_object, $is_reconnect, $options);
	}

    /**
     * update_or_insert the objects
     * @param  array $criteria   更新的条件
     * @param  array $new_object 更新的内容
     * @param  $upsert    true则插，false则不插
     * @param  $multi    false则更新找到的一条，ture则全部更新
     */
    public function update_or_insert($criteria, $new_object, $is_reconnect = false, $upsert = false,$multi=false)
    {
        if(!is_array($criteria)){
            throw new Exception("param must be array", Errno::PARAM_INVALID);
        }
        if(!is_array($new_object)){
            throw new Exception("param must be array", Errno::PARAM_INVALID);
        }
        return $this->db_handle->update($this->table, $criteria, $new_object, $is_reconnect, $upsert,$multi);
    }

	/**
	 * delete the objects 
	 * @param  array $criteria   删除的条件
	 * @param  array  $options    删除的额外设置
	 */
	public function delete($criteria, $is_reconnect = false, $options = array())
	{
		if(!is_array($criteria)){
			throw new Exception("param must be array", Errno::PARAM_INVALID);
		}
		return $this->db_handle->delete($this->table, $criteria, $is_reconnect, $options);
	}

	/**
	 * exec command 
	 * @param  array $command   要执行的MongoDB操作
	 */
	public function command($command)
	{
		if(!is_array($command)){
			throw new Exception("param must be array", Errno::PARAM_INVALID);
		}
		return $this->db_handle->command($command);
	}

	/**
	 * calculate aggregated values
	 * @param  array $criteria   删除的条件
	 * @param  array  $options    删除的额外设置
	 */
	public function aggregate($pipeline, $is_reconnect = false)
	{
		if(!is_array($pipeline)){
			throw new Exception("param must be array", Errno::PARAM_INVALID);
		}
		return $this->db_handle->aggregate($this->table, $pipeline, $is_reconnect);
	}
}

